#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node_Queue{
    int data;
    struct Node_Queue *next;
}Node_Q;

typedef struct Queue{
    Node_Q *head;
    Node_Q *tail;
}Queue;

Node_Q *init_qnode(void){
    Node_Q *nq = (Node_Q *)malloc(sizeof(Node_Q));
    if (nq == 0){
        printf("Node of Queue can't be initialized. \n");
    }else{
        memset(nq, 0, sizeof(Node_Q));
    }
}

Queue *init_queue(void){
    // Node_Q *nq = (Node_Q *)malloc(sizeof(Node_Q));
    // memset(nq, 0, sizeof(Node_Q));
    Queue *queue = (Queue *)malloc(sizeof(Queue));
    if (queue == 0){
        printf("Queue can't be Initialized! \n");
    }else {
        memset(queue, 0, sizeof(Queue));
    }
}

int determine_empty(Queue *duilie){
    return duilie->head == 0; // 0 or 1
}

void push_queue(Queue *duilie, int val){
    Node_Q *nq = init_qnode();
    nq->data = val;
    if (determine_empty(duilie)){
        duilie->head = nq;
        duilie->tail = nq;
    }else{
        duilie->tail->next = nq;  // last node point to new node
        duilie->tail = nq;  // tail point to tail node
    }
}

Node_Q *pop_queue(Queue *duilie){
    Node_Q *nq;
    if (duilie->head == 0){
        printf("Can't pop. Queue is Empty. \n");
        return duilie->head;
    }else{
        nq = duilie->head;
        duilie->head = duilie->head->next;
        return nq;
    }
}

void show_queue(Queue *duilie){
    if (duilie->head == 0){
        printf("Queue is Empty! \n");
        return;
    }
    Node_Q *nq = duilie->head;
    while(nq != 0){
        printf("%d ", nq->data);
        nq = nq->next;
    }
    printf("\n");
}

int main(void){
    Queue *duilie;
    duilie = init_queue();
    printf("Queue var has been Initialized @%p with size %lu! \n", duilie, sizeof(Queue));
    printf("Queue.head: {%p}, Queue.tail: {%p}. \n", duilie->head, duilie->tail);
    show_queue(duilie);

    int i;
    for (i=0; i<10; ++i){
        push_queue(duilie, i);
    }
    printf("10 values had been pushed to queue. \n");
    show_queue(duilie);

    Node_Q *popped; 
    for (i=0; i<10; ++i){
        popped = pop_queue(duilie);
        if (popped != 0) printf("Popped values is: %d. \n", popped->data);
        free(popped);
        show_queue(duilie);
    }
    return 0;
}